package com.sbc.design.chain;

import com.sbc.base.ApplicationContextHolder;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.Ordered;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @param <T> 请求参数的类型
 * @description: 抽象责任链上下文
 */
public class AbstractChainContext<T> implements CommandLineRunner {

    private final Map<String, List<AbstractChainHandler>> abstractChainHandlerContainer = new HashMap<>();

    @Override
    public void run(String... args) {
        // 获取所有具体执行者组件
        Map<String, AbstractChainHandler> chainFilterMap = ApplicationContextHolder.getBeansOfType(AbstractChainHandler.class);

        // 根据责任链组件标识将组件分类
        chainFilterMap.values().forEach(bean -> {
            abstractChainHandlerContainer
                    .computeIfAbsent(bean.mark(), k -> new ArrayList<>())
                    .add(bean);
        });

        // 按照组件 order 优先级进行排序
        abstractChainHandlerContainer.replaceAll((mark, handlers) ->
                handlers.stream()
                        .sorted(Comparator.comparing(Ordered::getOrder))
                        .collect(Collectors.toList())
        );
    }

    /**
     * 责任链组件执行
     *
     * @param mark         责任链组件标识
     * @param requestParam 请求参数
     */
    public void handler(String mark, T requestParam) {
        List<AbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(mark);
        if (CollectionUtils.isEmpty(abstractChainHandlers)) {
            throw new RuntimeException(String.format("[%s] 责任链标识未定义。", mark));
        }
        abstractChainHandlers.forEach(each -> each.handler(requestParam));
    }
}